#include "net/channel_post.h"
#include "net/channel_core.h"
#include "packet/packet.h"
#include "packet/packet_factory.h"
#include "controller/controller.h"
#include "callback/callback.h"
#include "log/log.h"
#include "thread/thread_manage.h"

namespace weilin {

	ChannelPost::ChannelPost(const call_back_shared_ptr& call_back_sp) :
    m_call_back_sp(call_back_sp)
	{
		m_send_packet_sp_map.clear();
		m_controller_sp_map.clear();
	}
	ChannelPost::~ChannelPost()
	{

	}
	void ChannelPost::PostRecvPacket(const channel_core_weak_ptr& channel_core_wp, const packet_shared_ptr& request_packet_sp)
	{
		//thread pool
		if (request_packet_sp->IsRequest() == true)
		{
			ThreadManage::Instance()->TreadPoolPost(boost::bind(&CallBack::RecvPacket, m_call_back_sp, channel_core_wp, request_packet_sp));
		}
		else
		{
			controller_shared_ptr controller_sp;
			if (FindRemoveControllerBySeq(request_packet_sp->GetSeq(), controller_sp) == false)
			{
				return;
			}
			controller_sp->m_recv_packet_sp = request_packet_sp;
			PostControllerSendRecvStatus(controller_sp, SEND_RECV_SECCESS);
		}
	}

	void ChannelPost::PostSocketStatus(const channel_core_shared_ptr& channel_core_sp, const SocketStatus& socket_status)
	{
		ThreadManage::Instance()->TreadPoolPost(boost::bind(&CallBack::SocketStateHandle, m_call_back_sp, channel_core_sp, socket_status));
	}


	void ChannelPost::PostControllerSendRecvStatus(const controller_shared_ptr& controller_sp, SendRecvStatus send_recv_status)
	{
		ThreadManage::Instance()->TreadPoolPost(boost::bind(&CallBack::SendRecvResult, m_call_back_sp, controller_sp, send_recv_status));
	}

	void ChannelPost::PostPacketSendStatus(const packet_shared_ptr& send_packet_sp, SendStatus send_status)
	{
		ThreadManage::Instance()->TreadPoolPost(boost::bind(&CallBack::SendResult, m_call_back_sp, send_packet_sp, send_status));
	}

	bool ChannelPost::InsertController(const controller_shared_ptr& controller_sp)
	{
		boost::unordered_map<uint32_t, controller_shared_ptr>::const_iterator conroller_it = m_controller_sp_map.find(controller_sp->GetSendPacket()->GetSeq());
		//already exist
		if (conroller_it != m_controller_sp_map.cend())
		{
			return false;
		}
		m_controller_sp_map.insert(std::pair<int, controller_shared_ptr>(controller_sp->GetSendPacket()->GetSeq(), controller_sp));
		return true;
	}


	bool ChannelPost::InsertPacket(const packet_shared_ptr& packet_sp)
	{
		boost::unordered_map<uint32_t, packet_shared_ptr>::const_iterator packet_it = m_send_packet_sp_map.find(packet_sp->GetSeq());
		if (packet_it != m_send_packet_sp_map.cend())
		{
			return false;
		}
		m_send_packet_sp_map.insert(std::pair<int, packet_shared_ptr>(packet_sp->GetSeq(), packet_sp));
		return true;
	}

	bool ChannelPost::GetFirstSendPacket(packet_shared_ptr& packet_sp)
	{
		boost::unordered_map<uint32_t, packet_shared_ptr>::const_iterator packet_it = m_send_packet_sp_map.cbegin();
		if (packet_it == m_send_packet_sp_map.cend())
		{
			return false;
		}
		packet_sp = packet_it->second;
		m_send_packet_sp_map.erase(packet_it);
		return true;
	}
	
	bool ChannelPost::FindRemovePacketBySeq(const uint32_t& seq, packet_shared_ptr& packet_sp)
	{
		boost::unordered_map<uint32_t, packet_shared_ptr>::const_iterator packet_it = m_send_packet_sp_map.find(seq);
		if (packet_it == m_send_packet_sp_map.cend())
		{
			return false;
		}
		packet_sp = packet_it->second;
		m_send_packet_sp_map.erase(packet_it);
		return true;
	}

	bool ChannelPost::FindRemoveControllerBySeq(const uint32_t& seq, controller_shared_ptr& controller_sp)
	{
		boost::unordered_map<uint32_t, controller_shared_ptr>::const_iterator conroller_it = m_controller_sp_map.find(seq);
		if (conroller_it == m_controller_sp_map.cend())
		{
			return false;
		}
		controller_sp = conroller_it->second;
		m_controller_sp_map.erase(conroller_it);
		return true;
	}

	void ChannelPost::ClearAllController()
	{
		for (boost::unordered_map<uint32_t, controller_shared_ptr>::const_iterator conroller_it = m_controller_sp_map.cbegin(); conroller_it != m_controller_sp_map.cend(); conroller_it++)
		{
			if (m_send_packet_sp_map.find(conroller_it->second->GetSendPacket()->GetSeq()) == m_send_packet_sp_map.cend())
			{
				PostControllerSendRecvStatus(conroller_it->second, SEND_FAIL_FOR_CLOSE);
			}
			else
			{
				PostControllerSendRecvStatus(conroller_it->second, RECV_FAIL_FOR_CLOSE);
			}
		}
		m_send_packet_sp_map.clear();
		m_controller_sp_map.clear();
	}

	void ChannelPost::ClearAllPacket()
	{
		for (boost::unordered_map<uint32_t, packet_shared_ptr>::const_iterator packet_it = m_send_packet_sp_map.cbegin(); packet_it != m_send_packet_sp_map.cend(); packet_it++)
		{
			PostPacketSendStatus(packet_it->second, SEND_ERROR_FOR_CLOSE);
		}
		m_send_packet_sp_map.clear();
		m_controller_sp_map.clear();
	}
}
